Enable the Xen hypervisor ACM security policy to be determined at boot
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Sat, 19 Nov 2005 09:35:38 +0000 (10:35 +0100)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Sat, 19 Nov 2005 09:35:38 +0000 (10:35 +0100)
time (instead of at compile time). Allows a single xen.gz binary to
run under different security policy types, which simplifies
distributions considerably. To this end, we replace the current single
compile switch in Config.mk with the following two:

1. ACM_SECURITY (y/n) if "n", then the ACM is not compiled and no security
policies can be configured at boot time. If "y", then the ACM is compiled
and can be configured into any of the available policy types (null,
chwall, ste, chwall_ste) by specifying a valid boot policy .bin file in
the grub boot configuration.

2. ACM_DEFAULT_SECURITY_POLICY (null / chwall / ste / chwall_ste)
specifies the policy into which Xen defaults in the case that security is
enabled but no boot policy file is specified, or the specified policy file
is invalid (wrong version, magic, corrupted, ...)

While the type of the enabled policy (null, ste, ...) is decided once
during boot for the whole boot cycle, the policy instantiation can be
changed during operation as usual with the security tools.

Signed-off by: Tomas Lendacky <toml@us.ibm.com>
Signed-off by: Reiner Sailer <sailer@us.ibm.com>

Config.mk
tools/security/Makefile
tools/security/install.txt
xen/Makefile
xen/Rules.mk
xen/acm/acm_core.c
xen/acm/acm_policy.c
xen/common/acm_ops.c
xen/include/acm/acm_core.h
xen/include/acm/acm_hooks.h
xen/include/public/acm.h

index 7bed4b8fe828a5cb913f6492de5a0a677ad708fa..3b24b07abed93de1bf27491b31b4665dbb3326b5 100644 (file)
--- a/Config.mk
+++ b/Config.mk
@@ -44,13 +44,21 @@ CFLAGS += $(foreach i, $(EXTRA_INCLUDES), -I$(i))
 # Choose the best mirror to download linux kernel
 KERNEL_REPO = http://www.kernel.org
 
-# ACM_USE_SECURITY_POLICY is set to security policy of Xen
+# If ACM_SECURITY = y, then the access control module is compiled
+# into Xen and the policy type can be set by the boot policy file
+#        y - Build the Xen ACM framework
+#        n - Do not build the Xen ACM framework
+ACM_SECURITY ?= n
+
+# If ACM_SECURITY = y and no boot policy file is installed,
+# then the ACM defaults to the security policy set by
+# ACM_DEFAULT_SECURITY_POLICY
 # Supported models are:
-#      ACM_NULL_POLICY (ACM will not be built with this policy)
+#      ACM_NULL_POLICY
 #      ACM_CHINESE_WALL_POLICY
 #      ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY
 #      ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY
-ACM_USE_SECURITY_POLICY ?= ACM_NULL_POLICY
+ACM_DEFAULT_SECURITY_POLICY ?= ACM_NULL_POLICY
 
 # Optional components
 XENSTAT_XENTOP ?= y
index ca77c2c81cee22081e5e777778ff47ab7d37a087..0d95a9b93f1957e67c199fd8c67422242ea9c451 100644 (file)
@@ -12,21 +12,21 @@ CFLAGS_XML2BIN += $(shell xml2-config --cflags --libs )
 XML2VERSION = $(shell xml2-config --version )
 VALIDATE_SCHEMA=$(shell if [[ $(XML2VERSION) < 2.6.20 ]]; then echo ""; else echo "-DVALIDATE_SCHEMA"; fi; )
 
-ifeq ($(ACM_USE_SECURITY_POLICY),ACM_NULL_POLICY)
+ifeq ($(ACM_DEFAULT_SECURITY_POLICY),ACM_NULL_POLICY)
 POLICY=null
 endif
-ifeq ($(ACM_USE_SECURITY_POLICY),ACM_CHINESE_WALL_POLICY)
+ifeq ($(ACM_DEFAULT_SECURITY_POLICY),ACM_CHINESE_WALL_POLICY)
 POLICY=chwall
 endif
-ifeq ($(ACM_USE_SECURITY_POLICY),ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY)
+ifeq ($(ACM_DEFAULT_SECURITY_POLICY),ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY)
 POLICY=ste
 endif
-ifeq ($(ACM_USE_SECURITY_POLICY),ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY)
+ifeq ($(ACM_DEFAULT_SECURITY_POLICY),ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY)
 POLICY=chwall_ste
 endif
 POLICYFILE=./policies/$(POLICY)/$(POLICY).bin
 
-ifneq ($(ACM_USE_SECURITY_POLICY), ACM_NULL_POLICY)
+ifeq ($(ACM_SECURITY),y)
 all: build
 
 install:all
@@ -55,7 +55,7 @@ secpol_xml2bin : secpol_xml2bin.c secpol_xml2bin.h
        $(CC) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_XML2BIN) $(VALIDATE_SCHEMA) -o $@ $<
 
 clean:
-       rm -rf secpol_tool secpol_xml2bin xen
+       rm -rf secpol_tool secpol_xml2bin xen get_decision
 
 policy_clean:
        rm -rf policies/*/*.bin policies/*/*.map
index e9156171555927727cd4e2127b33e0cab5b254b5..e67a7d6fe61760b4dc41133fe8ed658e5e6e6169 100644 (file)
@@ -24,11 +24,13 @@ exclusively (chwall_ste --> {chwall, ste}).
        # cd "xen_root"
        # edit/xemacs/vi Config.mk
 
-       change the line:
-       ACM_USE_SECURITY_POLICY ?= ACM_NULL_POLICY
+       change the lines:
+       ACM_SECURITY ?= n
+       ACM_DEFAULT_SECURITY_POLICY ?= ACM_NULL_POLICY
 
        to:
-       ACM_USE_SECURITY_POLICY ?= ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY
+       ACM_SECURITY ?= y
+       ACM_DEFAULT_SECURITY_POLICY ?= ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY
 
        # make all
        # ./install.sh
index d3a0bfd04d364f77b2075b1f5dff24b7bac4fb95..07d63bb57cf0e8580d561ab774163b1d9be84207 100644 (file)
@@ -57,7 +57,7 @@ $(TARGET): delete-unfresh-files
        $(MAKE) include/asm-$(TARGET_ARCH)/asm-offsets.h
        $(MAKE) -C common
        $(MAKE) -C drivers
-ifneq ($(ACM_USE_SECURITY_POLICY),ACM_NULL_POLICY)
+ifeq ($(ACM_SECURITY),y)
        $(MAKE) -C acm
 endif
        $(MAKE) -C arch/$(TARGET_ARCH)
@@ -79,8 +79,8 @@ include/xen/acm_policy.h:
          echo " *"; \
          echo " */"; \
          echo ""; \
-         echo "#ifndef ACM_USE_SECURITY_POLICY"; \
-         echo "#define ACM_USE_SECURITY_POLICY $(ACM_USE_SECURITY_POLICY)"; \
+         echo "#ifndef ACM_DEFAULT_SECURITY_POLICY"; \
+         echo "#define ACM_DEFAULT_SECURITY_POLICY $(ACM_DEFAULT_SECURITY_POLICY)"; \
          echo "#endif") >$@
 
 # compile.h contains dynamic build info. Rebuilt on every 'make' invocation.
index 484130c861a4302b1561ff5e297df1598de80f2a..0f43b4efa9a147b08d0c34ed43ad961a703d757d 100644 (file)
@@ -37,8 +37,9 @@ OBJS    += $(patsubst %.c,%.o,$(C_SRCS))
 ALL_OBJS := $(BASEDIR)/common/common.o
 ALL_OBJS += $(BASEDIR)/drivers/char/driver.o
 ALL_OBJS += $(BASEDIR)/drivers/acpi/driver.o
-ifneq ($(ACM_USE_SECURITY_POLICY),ACM_NULL_POLICY)
+ifeq ($(ACM_SECURITY),y)
 ALL_OBJS += $(BASEDIR)/acm/acm.o
+CFLAGS += -DACM_SECURITY
 endif
 ALL_OBJS += $(BASEDIR)/arch/$(TARGET_ARCH)/arch.o
 
index 456f186b7ad815d66e18d4ef2b52b5b00429604f..2e85abf38d3853b9e89e054a4a5a8e850ad1b880 100644 (file)
@@ -49,6 +49,9 @@ void acm_init_ste_policy(void);
 extern struct acm_operations acm_chinesewall_ops, 
     acm_simple_type_enforcement_ops, acm_null_ops;
 
+/* global ACM policy  (now dynamically determined at boot time) */
+u16 acm_active_security_policy = ACM_POLICY_UNDEFINED;
+
 /* global ops structs called by the hooks */
 struct acm_operations *acm_primary_ops = NULL;
 /* called in hook if-and-only-if primary succeeds */
@@ -61,7 +64,8 @@ rwlock_t acm_bin_pol_rwlock = RW_LOCK_UNLOCKED;
 
 /* until we have endian support in Xen, we discover it at runtime */
 u8 little_endian = 1;
-void acm_set_endian(void)
+void
+acm_set_endian(void)
 {
     u32 test = 1;
     if (*((u8 *)&test) == 1)
@@ -76,14 +80,82 @@ void acm_set_endian(void)
     }
 }
 
-/* initialize global security policy for Xen; policy write-locked already */
-static void
-acm_init_binary_policy(void *primary, void *secondary)
+int
+acm_init_binary_policy(u32 policy_code)
 {
-    acm_bin_pol.primary_policy_code = 0;
-    acm_bin_pol.secondary_policy_code = 0;
-    acm_bin_pol.primary_binary_policy = primary;
-    acm_bin_pol.secondary_binary_policy = secondary;
+    int ret = ACM_OK;
+
+    acm_bin_pol.primary_policy_code = (policy_code & 0x0f);
+    acm_bin_pol.secondary_policy_code = (policy_code >> 4) & 0x0f;
+
+    write_lock(&acm_bin_pol_rwlock);
+
+    /* set primary policy component */
+    switch ((policy_code) & 0x0f)
+    {
+
+    case ACM_CHINESE_WALL_POLICY:
+        acm_init_chwall_policy();
+        acm_bin_pol.primary_policy_code = ACM_CHINESE_WALL_POLICY;
+        acm_primary_ops = &acm_chinesewall_ops;
+        break;
+
+    case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
+        acm_init_ste_policy();
+        acm_bin_pol.primary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY;
+        acm_primary_ops = &acm_simple_type_enforcement_ops;
+        break;
+
+    case ACM_NULL_POLICY:
+        acm_bin_pol.primary_policy_code = ACM_NULL_POLICY;
+        acm_primary_ops = &acm_null_ops;
+        break;
+
+    default:
+        /* Unknown policy not allowed primary */
+        ret = -EINVAL;
+        goto out;
+    }
+
+    /* secondary policy component part */
+    switch ((policy_code) >> 4)
+    {
+
+    case ACM_NULL_POLICY:
+        acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY;
+        acm_secondary_ops = &acm_null_ops;
+        break;
+
+    case ACM_CHINESE_WALL_POLICY:
+        if (acm_bin_pol.primary_policy_code == ACM_CHINESE_WALL_POLICY)
+        {   /* not a valid combination */
+            ret = -EINVAL;
+            goto out;
+        }
+        acm_init_chwall_policy();
+        acm_bin_pol.secondary_policy_code = ACM_CHINESE_WALL_POLICY;
+        acm_secondary_ops = &acm_chinesewall_ops;
+        break;
+
+    case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
+        if (acm_bin_pol.primary_policy_code == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY)
+        {   /* not a valid combination */
+            ret = -EINVAL;
+            goto out;
+        }
+        acm_init_ste_policy();
+        acm_bin_pol.secondary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY;
+        acm_secondary_ops = &acm_simple_type_enforcement_ops;
+        break;
+
+    default:
+        ret = -EINVAL;
+        goto out;
+    }
+
+ out:
+    write_unlock(&acm_bin_pol_rwlock);
+    return ret;
 }
 
 static int
@@ -161,83 +233,35 @@ acm_init(unsigned int *initrdidx,
     int ret = ACM_OK;
 
     acm_set_endian();
-    write_lock(&acm_bin_pol_rwlock);
-    acm_init_binary_policy(NULL, NULL);
-
-    /* set primary policy component */
-    switch ((ACM_USE_SECURITY_POLICY) & 0x0f)
-    {
-
-    case ACM_CHINESE_WALL_POLICY:
-        acm_init_chwall_policy();
-        acm_bin_pol.primary_policy_code = ACM_CHINESE_WALL_POLICY;
-        acm_primary_ops = &acm_chinesewall_ops;
-        break;
 
-    case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
-        acm_init_ste_policy();
-        acm_bin_pol.primary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY;
-        acm_primary_ops = &acm_simple_type_enforcement_ops;
-        break;
+    /* first try to load the boot policy (uses its own locks) */
+    acm_setup(initrdidx, mbi, initial_images_start);
 
-    default:
-        /* NULL or Unknown policy not allowed primary;
-         * NULL/NULL will not compile this code */
-        ret = -EINVAL;
+    if (acm_active_security_policy != ACM_POLICY_UNDEFINED)
+    {
+        printk("%s: Boot-Policy. Enforcing %s: Primary %s, Secondary %s.\n", __func__,
+               ACM_POLICY_NAME(acm_active_security_policy),
+               ACM_POLICY_NAME(acm_bin_pol.primary_policy_code),
+               ACM_POLICY_NAME(acm_bin_pol.secondary_policy_code));
         goto out;
     }
+    /* else continue with the minimal hardcoded default startup policy */
+    printk("%s: Loading default policy (%s).\n",
+           __func__, ACM_POLICY_NAME(ACM_DEFAULT_SECURITY_POLICY));
 
-    /* secondary policy component part */
-    switch ((ACM_USE_SECURITY_POLICY) >> 4) {
-    case ACM_NULL_POLICY:
-        acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY;
-        acm_secondary_ops = &acm_null_ops;
-        break;
-
-    case ACM_CHINESE_WALL_POLICY:
-        if (acm_bin_pol.primary_policy_code == ACM_CHINESE_WALL_POLICY)
-        {   /* not a valid combination */
-            ret = -EINVAL;
-            goto out;
-        }
-        acm_init_chwall_policy();
-        acm_bin_pol.secondary_policy_code = ACM_CHINESE_WALL_POLICY;
-        acm_secondary_ops = &acm_chinesewall_ops;
-        break;
-
-    case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
-        if (acm_bin_pol.primary_policy_code == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY)
-        {   /* not a valid combination */
-            ret = -EINVAL;
-            goto out;
-        }
-        acm_init_ste_policy();
-        acm_bin_pol.secondary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY;
-        acm_secondary_ops = &acm_simple_type_enforcement_ops;
-        break;
-
-    default:
+    if (acm_init_binary_policy(ACM_DEFAULT_SECURITY_POLICY)) {
         ret = -EINVAL;
         goto out;
     }
+    acm_active_security_policy = ACM_DEFAULT_SECURITY_POLICY;
 
  out:
-    write_unlock(&acm_bin_pol_rwlock);
-
     if (ret != ACM_OK)
     {
         printk("%s: Error initializing policies.\n", __func__);
         /* here one could imagine a clean panic */
         return -EINVAL;
     }
-    if (acm_setup(initrdidx, mbi, initial_images_start) != ACM_OK)
-    {
-        printk("%s: Error loading policy at boot time.\n", __func__);
-        /* ignore, just continue with the minimal hardcoded startup policy */
-    }
-    printk("%s: Enforcing Primary %s, Secondary %s.\n", __func__, 
-           ACM_POLICY_NAME(acm_bin_pol.primary_policy_code),
-           ACM_POLICY_NAME(acm_bin_pol.secondary_policy_code));
     return ret;
 }
 
@@ -265,7 +289,7 @@ acm_init_domain_ssid(domid_t id, ssidref_t ssidref)
     ssid->primary_ssid   = NULL;
     ssid->secondary_ssid = NULL;
 
-    if (ACM_USE_SECURITY_POLICY != ACM_NULL_POLICY)
+    if (acm_active_security_policy != ACM_NULL_POLICY)
         ssid->ssidref = ssidref;
     else
         ssid->ssidref = ACM_DEFAULT_SSID;
index e316370993b719cc5e957a6ee2f55e99302f1af5..a581f7d723ac46675740e5fc935dec1e03f5390e 100644 (file)
@@ -56,17 +56,29 @@ acm_set_policy(void *buf, u32 buf_size, int isuserbuffer)
     /* 2. some sanity checking */
     pol = (struct acm_policy_buffer *)policy_buffer;
 
-    if ((ntohl(pol->magic) != ACM_MAGIC) || 
-        (ntohl(pol->policy_version) != ACM_POLICY_VERSION) ||
-        (ntohl(pol->primary_policy_code) != acm_bin_pol.primary_policy_code) ||
-        (ntohl(pol->secondary_policy_code) != acm_bin_pol.secondary_policy_code))
+    if ((ntohl(pol->magic) != ACM_MAGIC) ||
+        (buf_size != ntohl(pol->len)) ||
+        (ntohl(pol->policy_version) != ACM_POLICY_VERSION))
     {
-        printkd("%s: Wrong policy magics or versions!\n", __func__);
+        printk("%s: ERROR in Magic, Version, or buf size.\n", __func__);
         goto error_free;
     }
-    if (buf_size != ntohl(pol->len))
+
+    if (acm_active_security_policy == ACM_POLICY_UNDEFINED) {
+        /* setup the policy with the boot policy */
+        if (acm_init_binary_policy((ntohl(pol->secondary_policy_code) << 4) |
+                                   ntohl(pol->primary_policy_code))) {
+            goto error_free;
+        }
+        acm_active_security_policy =
+            (acm_bin_pol.secondary_policy_code << 4) | acm_bin_pol.primary_policy_code;
+    }
+
+    /* once acm_active_security_policy is set, it cannot be changed */
+    if ((ntohl(pol->primary_policy_code) != acm_bin_pol.primary_policy_code) ||
+        (ntohl(pol->secondary_policy_code) != acm_bin_pol.secondary_policy_code))
     {
-        printk("%s: ERROR in buf size.\n", __func__);
+        printkd("%s: Wrong policy type in boot policy!\n", __func__);
         goto error_free;
     }
 
index d290b40de63c71ab77d636591d1367f8a630f27f..1d19674a4ccee723a628ccc28fa9066b4a55f050 100644 (file)
@@ -29,7 +29,7 @@
 #include <public/sched_ctl.h>
 #include <acm/acm_hooks.h>
 
-#if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY)
+#ifndef ACM_SECURITY
 
 long do_acm_op(struct acm_op * u_acm_op)
 {
index eaa46ee3d5b2c900e98506888cdf15d387551153..7733192ad38f27cc86bad4c9e9b08585f7156b41 100644 (file)
@@ -28,9 +28,6 @@
 struct acm_binary_policy {
     u16 primary_policy_code;
     u16 secondary_policy_code;
-    void *primary_binary_policy;                                 
-    void *secondary_binary_policy;
 };
 
 struct chwall_binary_policy {
@@ -53,6 +50,7 @@ struct ste_binary_policy {
 };
 
 /* global acm policy */
+extern u16 acm_active_security_policy;
 extern struct acm_binary_policy acm_bin_pol;
 extern struct chwall_binary_policy chwall_bin_pol;
 extern struct ste_binary_policy ste_bin_pol;
@@ -120,6 +118,7 @@ struct ste_ssid {
 /* protos */
 int acm_init_domain_ssid(domid_t id, ssidref_t ssidref);
 void acm_free_domain_ssid(struct acm_ssid_domain *ssid);
+int acm_init_binary_policy(u32 policy_code);
 int acm_set_policy(void *buf, u32 buf_size, int isuserbuffer);
 int acm_get_policy(void *buf, u32 buf_size);
 int acm_dump_statistics(void *buf, u16 buf_size);
index 011669373dc54c8ee914b113b67bc3e8b5c20822..8208ef153ad06ba370738728a7e3bdde052a2158 100644 (file)
@@ -127,7 +127,7 @@ extern struct acm_operations *acm_secondary_ops;
 # define traceprintk(fmt, args...)
 #endif
 
-#if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY)
+#ifndef ACM_SECURITY
 
 static inline int acm_pre_dom0_op(dom0_op_t *op, void **ssid) 
 { return 0; }
index a6646c37926d08ec7e87cddd69ca662b1ff92e43..3db340a00d52193d7c1f5c003416baa6f979d1d6 100644 (file)
@@ -60,6 +60,7 @@
 #define ACM_NULL_POLICY 0
 #define ACM_CHINESE_WALL_POLICY 1
 #define ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY 2
+#define ACM_POLICY_UNDEFINED 15
 
 /* combinations have secondary policy component in higher 4bit */
 #define ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY \